package cn.net.mugui.web.tomcat;

import java.io.Serializable;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionContext;

import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.util.ArrayUtil;

public class SessionContext {
    @SuppressWarnings("serial")
    private static final TimedCache<String, TempSession> mymap = new TimedCache<String, TempSession>(60000 * 60 * 6) {
        @Override
        protected void onRemove(String key, TempSession cachedObject) {
            cachedObject.clear();
        }
    };

    static {
        mymap.schedulePrune(60000 * 60);
    }

    private static ThreadLocal<HttpSession> threadLocal = new ThreadLocal<>();

    public static synchronized void AddSession(HttpSession session) {
        if (session != null) {
            TempSession tempSession = mymap.get(session.getId());
            if (tempSession == null) {
                session.setMaxInactiveInterval(60 * 60 * 24);
                mymap.put(session.getId(), tempSession = new TempSession(session));
            } else {
                tempSession.session = session;
            }
            threadLocal.set(tempSession);
        }
    }

    public static HttpSession getLocalSession() {
        return threadLocal.get();
    }

    public static synchronized void DelSession(HttpSession session) {
        if (session != null) {
            try {
                Enumeration<String> attributeNames = session.getAttributeNames();
                while (attributeNames.hasMoreElements()) {
                    String string = attributeNames.nextElement();
                    session.removeAttribute(string);
                }
                mymap.remove(session.getId());
            } catch (Exception e) {
            }
            session.invalidate();
        }
    }

    public static void DelLocalSession() {
        DelSession(threadLocal.get());
        threadLocal.remove();
    }

    public static synchronized HttpSession getSession(String session_id) {
        if (session_id == null)
            return null;
        return mymap.get(session_id);
    }

    public static Iterator<TempSession> AllSession() {
        return mymap.iterator();
    }

//	private static Jedis redisClient = RedisAccess.getRedisClient(8);

    private static class TempSession implements HttpSession, Serializable {
        HttpSession session;
        private ConcurrentHashMap<String, Object> hashMap = new ConcurrentHashMap<String, Object>() {
            /**
             *
             */
            private static final long serialVersionUID = 1L;

            @Override
            public void clear() {
                for (Object object : hashMap.values()) {
                    if (object instanceof ReentrantLock) {
                        ReentrantLock lock = (ReentrantLock) object;
                        try {
                            if (lock.isHeldByCurrentThread())
                                lock.unlock();
                        } catch (Exception e) {
                        }
                    }
                }
                super.clear();
            }
        };

        public void clear() {
            hashMap.clear();
        }

        public TempSession(HttpSession session) {
            this.session = session;
        }

        public Object getAttribute(String key) {
            Object object = hashMap.get(key);
            if (object == null) {
                try {
                    object = session.getAttribute(key);
                } catch (Exception e) {
                    System.out.println("session getAttribute error:" + key);
                    removeAttribute(key);
                }
            }
            return object;
        }

        @Override
        public String getId() {
            return session.getId();
        }

        @Override
        public void setAttribute(String attributeName, Object attributeValue) {
            hashMap.put(attributeName, attributeValue);
            session.setAttribute(attributeName, attributeValue);
        }

        @Override
        public void removeAttribute(String attributeName) {
            hashMap.remove(attributeName);
            session.removeAttribute(attributeName);
        }

        @Override
        public long getCreationTime() {
            return session.getCreationTime();
        }

        @Override
        public long getLastAccessedTime() {
            return session.getLastAccessedTime();
        }

        @Override
        public ServletContext getServletContext() {
            return session.getServletContext();
        }

        @Override
        public void setMaxInactiveInterval(int interval) {
            session.setMaxInactiveInterval(interval);
        }

        @Override
        public int getMaxInactiveInterval() {
            return session.getMaxInactiveInterval();
        }

        @Override
        public HttpSessionContext getSessionContext() {
            return session.getSessionContext();
        }

        @Override
        public Object getValue(String name) {
            return getAttribute(name);
        }

        @Override
        public Enumeration<String> getAttributeNames() {
            return session.getAttributeNames();
        }

        @Override
        public String[] getValueNames() {
            return ArrayUtil.toArray(new HashSet<String>(hashMap.keySet()).iterator(), String.class);
        }

        @Override
        public void putValue(String name, Object value) {
            setAttribute(name, value);
        }

        @Override
        public void removeValue(String name) {
            removeAttribute(name);
        }

        @Override
        public void invalidate() {
            session.invalidate();
        }

        @Override
        public boolean isNew() {
            return session.isNew();
        }

    }

}
